package com.hongshu.idle.service.sys.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.GetResponse;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hongshu.common.core.constant.NoteConstant;
import com.hongshu.common.core.enums.PayStatusEnum;
import com.hongshu.common.core.enums.ProductTypeEnum;
import com.hongshu.common.core.utils.DateUtils;
import com.hongshu.idle.domain.entity.IdlePaymentOrder;
import com.hongshu.idle.domain.entity.IdlePaymentPay;
import com.hongshu.idle.domain.entity.IdleProduct;
import com.hongshu.idle.domain.entity.IdleProductOrder;
import com.hongshu.idle.domain.vo.IdleProductVO;
import com.hongshu.idle.mapper.idle.IdlePaymentOrderMapper;
import com.hongshu.idle.mapper.idle.IdlePaymentPayMapper;
import com.hongshu.idle.mapper.idle.IdleProductMapper;
import com.hongshu.idle.mapper.idle.IdleProductOrderMapper;
import com.hongshu.idle.service.sys.ISysIdlePaymentPayService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * 闲宝信息 服务层处理
 *
 * @author hongshu
 */
@Slf4j
@Service
public class SysIdlePaymentPayServiceImpl implements ISysIdlePaymentPayService {

    @Autowired
    private IdleProductMapper productMapper;
    @Autowired
    private IdleProductOrderMapper productOrderMapper;
    @Autowired
    private IdlePaymentOrderMapper paymentOrderMapper;
    @Autowired
    private IdlePaymentPayMapper paymentPayMapper;
    @Autowired
    private ElasticsearchClient elasticsearchClient;
    @Autowired
    private AlipayClient alipayClient;


    /**
     * 更新超时订单状态
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExpireStatus() {
        try {
            // 查询待支付且已超时的订单
            List<IdlePaymentPay> paymentPayList = paymentPayMapper
                    .selectList(new QueryWrapper<IdlePaymentPay>()
                            .eq("payment_status", PayStatusEnum.PEND_PAY.getCode())
                            .lt("payment_time_expire", new Date()));
            log.info("找到{}个超时待支付订单", paymentPayList.size());
            if (paymentPayList.size() <= 0) {
                return;
            }

            for (IdlePaymentPay pay : paymentPayList) {
                try {
                    this.handleOrder(pay, "expire");
                } catch (Exception e) {
                    log.error("处理超时订单失败, orderId: {}", pay.getOrderId(), e);
                }
            }
        } catch (Exception e) {
            log.error("更新超时订单状态失败", e);
            throw new RuntimeException("更新超时订单状态失败", e);
        }
    }

    /**
     * 定时查询并更新已支付订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePayStatus() {
        // 1. 只查询最近24小时的订单（沙箱订单有效期）
        Date expireTime = DateUtils.addHours(new Date(), -24);
        List<IdlePaymentPay> paymentPayList = paymentPayMapper.selectList(
                new QueryWrapper<IdlePaymentPay>()
                        .eq("payment_status", PayStatusEnum.PEND_PAY.getCode())
                        .ge("create_time", expireTime) // 避免查询过期订单
        );
        log.info("找到{}个已支付订单", paymentPayList.size());
        if (paymentPayList.size() <= 0) {
            return;
        }

        // 2. 分批处理（防止大事务）
        for (IdlePaymentPay pay : paymentPayList) {
            try {
                this.checkSingleOrder(pay);
            } catch (Exception e) {
                log.error("订单状态检查失败: orderId={}", pay.getOrderId(), e);
                // 继续处理下一个订单（不因单个失败中断整个任务）
            }
        }
    }

    /**
     * 分批处理订单
     */
    @SneakyThrows
    private void checkSingleOrder(IdlePaymentPay pay) {
        IdlePaymentOrder order = paymentOrderMapper.selectById(pay.getOrderId());
        // 3. 调用支付宝查询接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{\"out_trade_no\":\"" + order.getOrderNumber() + "\"}");
        AlipayTradeQueryResponse response = alipayClient.execute(request);

        // 4. 处理查询结果（严格状态判断）
        if (response.isSuccess()) {
            String tradeStatus = response.getTradeStatus();
            if ("TRADE_SUCCESS".equals(tradeStatus)) {
//                // 5. 加锁更新（防止并发重复更新）
//                boolean lockAcquired = redisLock.tryLock(
//                        "pay:update:" + pay.getOrderId(),
//                        30, TimeUnit.SECONDS
//                );
//                if (lockAcquired) {
                try {
                    // 6. 再次确认状态（防止处理期间状态变化）
                    IdlePaymentPay paymentPay = paymentPayMapper.selectById(pay.getId());
                    if (PayStatusEnum.PEND_PAY.getCode().equals(paymentPay.getPaymentStatus())) {
                        // 更新状态
                        this.handleOrder(paymentPay, "pay");
                    }
                } finally {
//                    redisLock.unlock("pay:update:" + pay.getOrderId());
                }
//                }
            } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                // 处理已关闭订单
//                markOrderAsClosed(pay);
            }
        }
    }

    /**
     * 更新状态
     */
    private void handleOrder(IdlePaymentPay pay, String type) {
        Date updateTime = new Date();

        // 更新支付表状态
        this.updatePaymentPay(pay, type, updateTime);

        // 更新支付订单表状态
        IdlePaymentOrder paymentOrder = this.updatePaymentOrder(pay, type, updateTime);

        // 更新产品订单表状态
        IdleProductOrder productOrder = this.updateProductOrder(paymentOrder, type, updateTime);

        // 更新产品状态
        this.updateProduct(productOrder, type, updateTime);
    }

    /**
     * 更新支付表状态
     */
    private void updatePaymentPay(IdlePaymentPay pay, String type, Date updateTime) {
        if ("expire".equals(type)) {
            pay.setPaymentStatus(PayStatusEnum.UN_PAY.getCode());
        }
        if ("pay".equals(type)) {
            pay.setPaymentStatus(PayStatusEnum.PAY.getCode());
        }
        pay.setFinishTime(updateTime);
        pay.setUpdateTime(updateTime);
        paymentPayMapper.updateById(pay);
    }

    /**
     * 更新支付订单表状态
     */
    private IdlePaymentOrder updatePaymentOrder(IdlePaymentPay pay, String type, Date updateTime) {
        IdlePaymentOrder paymentOrder = paymentOrderMapper
                .selectOne(new QueryWrapper<IdlePaymentOrder>()
                        .eq("id", pay.getOrderId()));
        if ("expire".equals(type)) {
            paymentOrder.setOrderStatus(PayStatusEnum.UN_PAY.getCode());
        }
        if ("pay".equals(type)) {
            paymentOrder.setOrderStatus(PayStatusEnum.PAY.getCode());
        }
        paymentOrder.setUpdateTime(updateTime);
        paymentOrderMapper.updateById(paymentOrder);
        return paymentOrder;
    }

    /**
     * 更新产品订单表状态
     */
    private IdleProductOrder updateProductOrder(IdlePaymentOrder paymentOrder, String type, Date updateTime) {
        IdleProductOrder productOrder = productOrderMapper
                .selectOne(new QueryWrapper<IdleProductOrder>()
                        .eq("payment_order_id", paymentOrder.getId()));
        if ("expire".equals(type)) {
            productOrder.setOrderStatus(PayStatusEnum.UN_PAY.getCode());
        }
        if ("pay".equals(type)) {
            productOrder.setOrderStatus(PayStatusEnum.PAY.getCode());
        }
        productOrder.setUpdateTime(updateTime);
        productOrderMapper.updateById(productOrder);
        return productOrder;
    }

    /**
     * 更新产品状态
     */
    private void updateProduct(IdleProductOrder productOrder, String type, Date updateTime) {
        IdleProduct product = productMapper.selectById(productOrder.getProductId());
        if ("expire".equals(type)) {
            product.setBuyUid("");
            product.setStatus(Integer.valueOf(PayStatusEnum.UN_PAY.getCode()));
        }
        if ("pay".equals(type)) {
            product.setType(ProductTypeEnum.SELL_OUT.getCode());
            product.setStatus(Integer.valueOf(PayStatusEnum.PAY.getCode()));
        }
        product.setUpdateTime(updateTime);
        productMapper.updateById(product);

        // 更新ES数据
        this.updateEsProduct(product.getId(), 0);
    }

    /**
     * 更新ES数据
     */
    private void updateEsProduct(String productId, int status) {
        try {
            GetResponse<IdleProductVO> getResponse = elasticsearchClient.get(g -> g
                    .index(NoteConstant.PRODUCT_INDEX)
                    .id(productId), IdleProductVO.class);

            if (getResponse.found()) {
                IdleProductVO productSearchVO = getResponse.source();
                productSearchVO.setStatus(status);
                elasticsearchClient.update(u -> u
                        .index(NoteConstant.PRODUCT_INDEX)
                        .id(productId)
                        .doc(productSearchVO), IdleProductVO.class);
            }
        } catch (Exception e) {
            log.error("更新ES产品数据失败, productId: {}", productId, e);
        }
    }
}
